# -*- coding: utf-8 -*-

from myCryption import validate_license_code
from tkinter.filedialog import askopenfilename
import re
import tkinter as tk
from tkinter import messagebox, filedialog, scrolledtext, PanedWindow, ttk
import pandas as pd
import hashlib
import chardet
import csv
import os
import traceback
from datetime import datetime
from collections import defaultdict

# ==================== 全局变量声明 ====================
output_textbox = None


# ==================== 工具函数 ====================
def show_error(title, message):
    """统一错误提示"""
    messagebox.showerror(title, f"❌ 错误详情：\n{message}")


def debug_print(message):
    """调试信息输出到主窗口"""
    # return
    global output_textbox
    if output_textbox:
        timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
        output_textbox.insert(tk.END, f"[{timestamp}] {message}\n")
        output_textbox.see(tk.END)
        output_textbox.update_idletasks()
    else:
        print(f"[DEBUG] {message}")


def log_exception(ex):
    """异常日志记录"""
    error_msg = f"""
    ⚠️ 异常类型：{type(ex).__name__}
    📌 错误信息：{str(ex)}
    🛠 堆栈跟踪：
    {traceback.format_exc()}
    """
    debug_print(error_msg)
    show_error("系统异常", error_msg)


def clean_hex_value(value):
    """清洗并验证十六进制值（增加大小写处理）"""
    try:
        # 统一处理：去除空格、0x前缀，转大写
        cleaned = str(value).strip().upper().replace('0X', '')
        if not cleaned:
            return None
        # 验证是否为有效十六进制
        int(cleaned, 16)
        return f"{cleaned.zfill(2)}"  # 生成大写两位格式
    except:
        return None

# 将输入的十六进制数据转换为C语言数组格式
def convert_hex_to_array(hex_data):
    converted_data = []
    hex_list = hex_data.split()

    start_index = 0

    max_data_count = len(hex_list)
    end_index = min(start_index + max_data_count, len(hex_list))
    data_to_convert = hex_list[start_index:end_index]

    # 格式化为C语言数组
    formatted_data = [f"0x{value}" for value in data_to_convert]

    lines = [", ".join(formatted_data[i:i+8]) + ("," if i+8 < len(formatted_data) else "") for i in range(0, len(formatted_data), 8)]


    return lines


def generate_bta_processing_code(bta_data):
    output_code = ""
    if not bta_data:
        return output_code

    # 用于存储已处理的 switch_var
    processed_switches = set()

    # 用于记录每个 switch_var 的重复数组名字
    switch_duplicate_names = {}

    output_code += "static int mipi_bta_process(uint32_t data, uint32_t data_bak, uint32_t data_bak2)"
    output_code += "\n{"
    output_code += "\n  uint8_t data0 = 0, data1 = 0, data2 = 0, data3 = 0;"
    output_code += "\n  data0 = (data >> 0)  &  0xff;"
    output_code += "\n  data1 = (data >> 8)  &  0xff;"
    output_code += "\n  data2 = (data >> 16) &  0xff;"
    output_code += "\n  data3 = (data >> 24) &  0xff;"
    output_code += '\n  \\\\printf("BT1:0x%x, T2:0x%x, T3:0x%x\\r\\n", data, data_bak, data_bak2);'
    output_code += "\n"
    output_code += "\n  switch(data0)"
    output_code += "\n  {"

    # 遍历 bta_data
    for item in bta_data:
        # 解析数组名，假设数组名格式为 BTA_XX_YY
        array_name_parts = item.split("_")
        if len(array_name_parts) < 3:
            continue

        switch_var = array_name_parts[1]  # 第一个 switch 的 case 变量
        case_var = array_name_parts[2]  # 第二个 switch 的 case 变量

        # 如果该 switch_var 还没处理过，则生成外层 switch 代码
        if switch_var not in processed_switches:
            if processed_switches:
                # 如果已经有处理过的 switch_var，先闭合上一个 case 的大括号
                output_code += "    }\n"
            processed_switches.add(switch_var)
            output_code += "\n"
            output_code += f"    case 0x{switch_var}:\n"
            output_code += "    {\n"  # 开始外层 case 的大括号

            # 生成内层 switch(data1) 结构，根据 case_var 动态生成 case 分支
            output_code += "      switch(data1)\n"
            output_code += "      {\n"

            # 用于记录已经处理过的 case_var
            processed_cases = set()

            # 动态生成 case 分支
            for inner_item in bta_data:
                inner_array_name_parts = inner_item.split("_")
                if len(inner_array_name_parts) < 3:
                    continue
                inner_switch_var = inner_array_name_parts[1]
                inner_case_var = inner_array_name_parts[2]
                if inner_switch_var == switch_var:

                    # 记录重复的数组名字
                    if inner_case_var in switch_duplicate_names.get(switch_var, set()):
                        output_code += f"            // WARNING: '{inner_item}'BTA数组与其他数组为同一个指令头，但回复内容不同请自行做兼容!\n"
                    else:
                        switch_duplicate_names.setdefault(switch_var, set()).add(inner_case_var)

                    if inner_case_var not in processed_cases:
                        processed_cases.add(inner_case_var)
                        output_code += f"        case 0x{inner_case_var}:\n"
                        output_code += f"            device_cmd_response({inner_item}, sizeof({inner_item}));\n"
                        # output_code += f"            // printf({inner_item} bta: 0x%x\\n, data)\n"
                        output_code += f"            break;\n"


            output_code += "        default:\n"
            output_code += f"            // printf(other {switch_var} bta: 0x%x\\n, data)\n"
            output_code += "            break;\n"
            output_code += "      }\n"
            output_code += "      break;\n"  # 跳出外层 switch(data1)

    if processed_switches:
        output_code += "    }\n"  # 闭合最后一个 case 的大括号

    output_code += "\n"
    output_code += "    default:\n"
    output_code += '        // printf(other bta: 0x%x\\n, data)\n'
    output_code += "        break;\n"

    output_code += "  }\n"
    output_code += "}\n"

    return output_code


def extract_array_names(bta_data):
    array_names = []
    for item in bta_data:
        # 寻找形如 "uint32_t BTA_06_04" 或 "uint32_t BTA_06_04_1" 的数组名
        start_idx = item.find("BTA_")
        if start_idx != -1:
            end_idx = item.find(" ", start_idx)
            if end_idx == -1:
                end_idx = item.find("=", start_idx)
            if end_idx != -1:
                array_name = item[start_idx:end_idx].strip()
                array_names.append(array_name[:-2])
    return array_names


def process_bta_data(bta_data):
    array_counts = defaultdict(int)
    unique_bta_data = []

    # 使用字典来存储已经处理过的数组内容
    seen_arrays = defaultdict(set)

    for item in bta_data:
        array_name_start = item.find("BTA_")  # 找到数组名的起始位置
        if array_name_start != -1:
            array_name_end = item.find(" ", array_name_start)  # 找到数组名的结束位置
            if array_name_end != -1:
                array_name = item[array_name_start:array_name_end]  # 提取数组名部分
                array_content = item[array_name_end + 1:].strip()  # 提取数组内容部分

                if array_content in seen_arrays[array_name]:
                    # 如果数组名和内容已经存在于 seen_arrays 中，则不添加到 unique_bta_data 中
                    continue

                seen_arrays[array_name].add(array_content)

                if array_name in array_counts:
                    # array_counts[array_name] += 1
                    # new_array_name = f"{array_name}_{array_counts[array_name]}"
                    # 去除 array_name 中的 `[` 和 `]`
                    clean_array_name = array_name.replace('[', '').replace(']', '')
                    new_array_name = f"{clean_array_name}_{array_counts[array_name]}[]"
                    unique_bta_data.append(item.replace(array_name, new_array_name, 1))
                else:
                    array_counts[array_name] = 0
                    unique_bta_data.append(item)
            else:
                unique_bta_data.append(item)
        else:
            unique_bta_data.append(item)

    return unique_bta_data


def select_files_and_process():
    file_paths = filedialog.askopenfilenames(
        title="选择一个或多个CSV文件",
        filetypes=[("CSV Files", "*.csv")]
    )
    if file_paths:
        # 创建 Tkinter 窗口
        root = tk.Tk()
        root.withdraw()  # 隐藏主窗口

        # 创建输出文本框窗口
        output_window = tk.Toplevel(root)
        output_window.title("处理结果")
        output_textbox = scrolledtext.ScrolledText(output_window, wrap=tk.WORD, height=30, width=100)
        output_textbox.pack(fill=tk.BOTH, expand=True)  # 自适应大小

        # 处理选择的文件
        read_csv_and_process_bta(output_textbox, file_paths)

        # 运行 Tkinter 事件循环
        root.mainloop()


def read_csv_and_process_bta(output_textbox, file_paths):
    bta_data = []
    debug_info = []  # 用于存储调试信息
    dt_index = None
    d0_index = None
    wc_index = None  # 添加了 WC 的索引
    lp_bta_count = 0  # 记录 LP_BTA 的计数
    processing_lp_bta = False  # 标记是否正在处理 LP_BTA 的下一行数据
    pps_collecting = False
    pps_data =[]
    pps_11_flag = False
    wc_value_str = ''
    bta_wc_empty = False
    temp_wc = 0
    for file_path in file_paths:
        file_name = os.path.splitext(os.path.basename(file_path))[0]  # 获取文件名，不包括扩展名
        try:
            with open(file_path, 'r', encoding='utf-8-sig') as csvfile:
                csvreader = csv.reader(csvfile)
                header = next(csvreader)  # 读取标题行

                # 确定 DT、D0 和 WC 的索引
                if header:
                    dt_index = header.index("DT")
                    d0_index = header.index("D0")
                    wc_index = header.index("WC")

                previous_row = None
                for row_num, row in enumerate(csvreader, start=2):  # 行号从第二行开始计数
                    debug_info.append(f"处理第 {row_num} 行数据...")

                    mode = row[1].strip().strip('="')  # 去除额外的等号和引号
                    dt_value = row[dt_index].strip().strip('="') if dt_index is not None else ''
                    d0_value = row[d0_index].strip().strip('="') if d0_index is not None else ''
                    data_values = [val.strip() for val in row[6:14] if val.strip() and val.strip().startswith("0x")]
                    wc_value_str = row[wc_index].strip().strip('="')
                    # print(wc_value_str)
                    debug_info.append(f"Mode: {mode}, DT: {dt_value}, D0: {d0_value}")

                    # 处理长包bta的剩余部分
                    if bta_wc_empty:
                        elements_to_process = min(temp_wc, 8)  # 每次最多处理8个元素
                        additional_data.extend(
                            [val.strip().strip('="') for val in row[7:7 + elements_to_process] if
                             val.strip() and val.strip()])
                        temp_wc -= elements_to_process
                        if temp_wc > 0:
                            bta_wc_empty = True
                            continue
                        # 构建数组名称和数据
                        array_name = f"uint32_t BTA_{previous_dt_value}_{previous_d0_value}[]"

                        long_package_data = []
                        wc1 = wc_value[0:2] if len(wc_value) > 1 else '00'
                        wc0 = wc_value[2:4] if len(wc_value) > 3 else '00'
                        first_line_data = f"00{wc1}{wc0}{dcs_value}"
                        long_package_data.append(first_line_data)

                        for i in range(2, len(additional_data), 4):
                            # 反转  bta长包数据为  D3D2D1D0
                            chunk = list(reversed(additional_data[i:i + 4]))
                            # print(chunk)
                            # print(type(chunk))
                            if len(chunk) < 4:
                                chunk = ['00'] * (4 - len(chunk)) + chunk
                                # print("len")
                            # else:

                            chunk = ['0x'] + chunk
                            long_package_data.append(''.join(chunk))

                        array_content = ',\n'.join(long_package_data)
                        bta_data.append(f"{array_name} = {{\n0x{array_content}\n}};")
                        debug_info.append(f"提取的数组名称: {array_name}")
                        print(additional_data)
                        bta_wc_empty = False
                        processing_lp_bta = False

                    if processing_lp_bta:
                        # 处理 LP_BTA 的下一行数据
                        if mode == 'LP_ESC':
                            # 提取 DCS
                            dcs_value = row[dt_index].strip().strip('="')[-3:-1] if len(row) > 6 else ''
                            if dcs_value:
                                # 提取 WC
                                if wc_value_str == ' ':
                                    wc_value = '0002'
                                else:
                                    wc_value = wc_value_str[-4:]

                                # 检查 WC 是否有效
                                if all(c in '0123456789abcdefABCDEF' for c in wc_value) and len(wc_value) == 4:
                                    wc_value_int = int(wc_value, 16)
                                    temp_wc = wc_value_int
                                    # # 获取后续数据
                                    # additional_data = [f"0x{dcs_value}"]
                                    # additional_data.extend([wc_value])
                                    # additional_data.extend([val.strip().strip('="') for val in row[7:7 + wc_value_int] if
                                    #                         val.strip() and val.strip()])
                                    # 获取后续数据
                                    additional_data = [f"0x{dcs_value}"]
                                    additional_data.extend([wc_value])
                                    # TODO 这里需要再做一层处理 此时无法获取下一行的数据，若是wc超过8 则会提取到 ecc crc等数据 所以使用min限制
                                    # 但是还是无没有获取到下一层的数据
                                    elements_to_process = min(temp_wc, 8)  # 每次最多处理8个元素
                                    additional_data.extend(
                                        [val.strip().strip('="') for val in row[7:7 + elements_to_process] if
                                         val.strip() and val.strip()])
                                    temp_wc -= elements_to_process
                                    if temp_wc > 0:
                                        bta_wc_empty = True
                                        continue
                                    # 构建数组名称和数据
                                    array_name = f"uint32_t BTA_{previous_dt_value}_{previous_d0_value}[]"

                                    if wc_value_int > 2:
                                        long_package_data = []
                                        wc1 = wc_value[0:2] if len(wc_value) > 1 else '00'
                                        wc0 = wc_value[2:4] if len(wc_value) > 3 else '00'
                                        first_line_data = f"00{wc1}{wc0}{dcs_value}"
                                        long_package_data.append(first_line_data)

                                        for i in range(2, len(additional_data), 4):
                                            # 反转  bta长包数据为  D3D2D1D0
                                            chunk = list(reversed(additional_data[i:i + 4]))
                                            # print(chunk)
                                            # print(type(chunk))
                                            if len(chunk) < 4:
                                                chunk = ['00'] * (4 - len(chunk)) + chunk
                                                # print("len")
                                            # else:

                                            chunk = ['0x'] + chunk
                                            long_package_data.append(''.join(chunk))

                                        array_content = ',\n'.join(long_package_data)
                                        bta_data.append(f"{array_name} = {{\n0x{array_content}\n}};")
                                        debug_info.append(f"提取的数组名称: {array_name}")

                                    else:
                                        short_package_data = ['\n''0x00', '00']
                                        if len(additional_data) > 2:
                                            short_package_data.append(additional_data[2])
                                        else:
                                            short_package_data.append('00')
                                        short_package_data.append(dcs_value + '\n')

                                        array_content = ''.join(short_package_data)

                                        bta_data.append(f"{array_name} = {{{array_content}}};")
                                        debug_info.append(f"提取的数组名称: {array_name}")

                                else:
                                    debug_info.append(f"错误：无效的十六进制字符 '{wc_value}' 或长度不为4")

                            processing_lp_bta = False

                    if mode == 'LP_BTA':
                        lp_bta_count += 1
                        debug_info.append(f"LP_BTA 计数: {lp_bta_count}")

                        if lp_bta_count % 2 != 0:
                            if previous_row:
                                previous_dt_value = previous_row[dt_index].strip().strip('="')[
                                                    -3:-1] if dt_index is not None else ''
                                previous_d0_value = previous_row[d0_index].strip().strip(
                                    '="') if d0_index is not None else ''
                                debug_info.append(f"Previous DT value: {previous_dt_value}")
                                debug_info.append(f"Previous D0 value: {previous_d0_value}")

                                if previous_dt_value and previous_d0_value:
                                    processing_lp_bta = True
                                else:
                                    debug_info.append("未找到 DT 或 D0 中的数字部分")
                    # # 检查是否为 PPS 数据
                    # if wc_value_str:
                    #     print("sec" + wc_value_str)
                    if any(val in dt_value for val in ['39', '0A']) and any(val in wc_value_str for val in ['80', '59', '81', '5A', '89']):
                        pps_collecting = True
                        # print("pps get 1")
                        pps_data_list = []

                    if pps_collecting:
                        # 读取后续数据（最多100个数据，跨行读取）
                        pps_values = [row[7:14]]  # 假设数据在第6到14列
                        if '11' == row[7].strip().strip('=\"'):
                            # print('11')
                            pps_11_flag = True
                        # print(pps_values)
                        for _ in range(14):  # 最多读取12行数据
                            try:
                                next_row = next(csvreader)
                                pps_values.append(next_row[7:14])
                                # print(next_row[7:14])
                            except StopIteration:
                                break
                        # 扁平化数据并格式化
                        # flattened_values = [f"0x{val.strip().strip('=\"')}," for sublist in pps_values for val in
                        #                     sublist if val.strip()]  pythonv3.8版本不支持这种写法 可能会有bug
                        flattened_values = [f"0x{val.strip().strip('')}," for sublist in pps_values for val in
                                            sublist if val.strip()]

                        # 调试输出
                        # print("原始数据：", pps_values)
                        # print("扁平化后的数据：", flattened_values)

                        # if len(flattened_values) > 120:
                        #     if pps_11_flag:
                        #         flattened_values = flattened_values[:128]
                        #         print("pps_11_flag")
                        #     else:
                        #         flattened_values = flattened_values[1:129]
                        # else:
                        if pps_11_flag:
                            flattened_values = flattened_values[:-1]
                            print("pps_11_flag")
                        else:
                            flattened_values = flattened_values[1:-1]

                        # 计算当前元素数量
                        current_count = len(flattened_values)
                        # 补充到 128 个元素 方便复制粘贴
                        if current_count < 128:
                            # 计算需要补充多少个
                            num_to_add = 128 - current_count
                            # 补充 0x00
                            flattened_values.extend(["0x00,"] * num_to_add)
                        # 每八个数据一组
                        grouped_values = [flattened_values[i:i + 8] for i in range(0, len(flattened_values), 8)]

                        # 格式化每行
                        formatted_pps_data = '\n'.join([' '.join(group) for group in grouped_values])
                        pps_data.append(f"PPS 数据 ({file_name}):\n{formatted_pps_data}")
                        pps_collecting = False

                    debug_info.append(f"当前行数据 - Mode: {mode}, DT: {dt_value}, D0: {d0_value}, 数据: {', '.join(data_values)}")

                    previous_row = row

            bta_data = process_bta_data(bta_data)

            output_textbox.delete('1.0', tk.END)
            if bta_data:
                output_textbox.insert(tk.END, "提取的 BTA 数据:\n")
                for item in bta_data:
                    output_textbox.insert(tk.END, item + "\n")
            else:
                output_textbox.insert(tk.END, "未找到符合条件的 BTA 数据。\n")

            if pps_data:
                # print("pps get")
                #创建新的窗口
                pps_window = tk.Toplevel()
                pps_window.title("PPS 数据")

                # 创建 Text 组件
                pps_textbox = tk.Text(pps_window, wrap=tk.WORD)
                # 自适应大小
                pps_textbox.pack(fill=tk.BOTH, expand=True)

                # 插入 PPS 数据
                for item in pps_data:
                    pps_textbox.insert(tk.END, item + "\n")
                # 插入格式化后的 PPS 数据
                # pps_textbox.insert(tk.END, formatted_pps_data)

                # 可选：为窗口添加滚动条（如果需要）
                scrollbar = tk.Scrollbar(pps_window, orient=tk.VERTICAL, command=pps_textbox.yview)
                scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
                pps_textbox.config(yscrollcommand=scrollbar.set)

                # 更新窗口大小
                pps_window.update_idletasks()

        except FileNotFoundError:
            output_textbox.delete('1.0', tk.END)
            output_textbox.insert(tk.END, f"错误：找不到文件 {file_path}\n")
        except Exception as e:
            output_textbox.delete('1.0', tk.END)
            output_textbox.insert(tk.END, f"错误：{str(e)}\n")
    # 提取数组名并展示处理后的代码
    array_names = extract_array_names(bta_data)
    bta_code = generate_bta_processing_code(array_names)

    code_window = tk.Toplevel()
    code_window.title("生成的bta代码")
    code_textbox = tk.Text(code_window, wrap=tk.WORD, height=30, width=100)
    code_textbox.insert(tk.END, bta_code)
    code_textbox.pack(fill=tk.BOTH, expand=True)  # 自适应大小


# 处理按钮点击事件：选择并处理 CSV 文件
def handle_read_csv(output_textbox, file_path):
    output_textbox.delete('1.0', tk.END)  # 清空文本框

    try:
        with open(file_path, 'r', newline='', encoding='utf-8-sig') as csvfile:
            reader = csv.reader(csvfile)
            for row in reader:
                output_textbox.insert(tk.END, ', '.join(row) + '\n')

        if output_textbox.get('1.0', tk.END).strip() == '':
            output_textbox.insert(tk.END, "未找到数据或文件为空。\n")

    except FileNotFoundError:
        output_textbox.insert(tk.END, f"错误：找不到文件 {file_path}\n")
    except Exception as e:
        output_textbox.insert(tk.END, f"错误：{str(e)}\n")


def open_csv_file_and_process():
    file_paths = filedialog.askopenfilenames(
        title="选择一个或多个CSV文件",
        filetypes=[("CSV Files", "*.csv")]
    )
    if file_paths:
        read_csv_and_process_bta(output_textbox, file_paths)


def extract_specific_command_data(text, command_name, header_value=None, index_start=0,
                                  start_find_value="(", end_find_value=")", include_non_hex=False,
                                  use_alternative_rule=False, skip_data=0, separator=","):
    # 检查并处理默认参数
    if text is None:
        raise ValueError("参数 'text' 不能为空")

    # 初始化返回的数据
    extracted_data = []
    extracted_array_name = []

    lines = text.splitlines()
    index = index_start

    for line in lines:
        line = line.split('//')[0].strip()
        if use_alternative_rule:
            # 处理新规则
            # print(f"原始行: {line}")
            if line.startswith(command_name):
                # 提取自定义分隔符的数据
                data_parts = line[len(command_name):].strip().split(separator)
                # print(f"提取的数据部分: {data_parts}")

                # 跳过指定的数据
                if skip_data > 0 and len(data_parts) >= skip_data:
                    # print(f"跳过第 {skip_data} 个数据，原数据: {data_parts}")
                    data_parts.pop(skip_data - 1)  # 跳过第 skip_data 个数据（索引从0开始）
                    # print(f"跳过后的数据部分: {data_parts}")

                # 构建 hex_data
                hex_data = [f"0x{part.strip()}" for part in data_parts]
                if header_value is None:
                    header_value = 0x29  # 默认指令头为0x29

                array_name = f"cmd{index}"
                data_length = len(hex_data)
                array_content = [f"0x{header_value:02X}", f"0x{data_length:02X}"] + ["0x00"] + hex_data
                array_definition = f"static uint8_t {array_name}[] = {{{', '.join(array_content)}}};"
                extracted_data.append(array_definition)
                index += 1
        else:
            # 处理现有规则
            if line.startswith(command_name):
                # 使用用户提供的 start_find_value 和 end_find_value
                start_find_pos = line.find(start_find_value)
                end_find_pos = line.find(end_find_value, start_find_pos)
                print(f"start_value{start_find_value},end_value{end_find_value}")
                if end_find_pos == start_find_pos or end_find_pos == -1:
                    print("end_pos=start or end_pos=-1")
                    end_find_pos = len(line)
                if start_find_pos == -1 or end_find_pos == -1:
                    continue

                start_idx = start_find_pos + 1
                end_idx = end_find_pos

                if end_idx <= start_idx:
                    continue

                params_str = line[start_idx:end_idx].strip()

                # 使用用户提供的分隔符分割数据
                params = params_str.split(separator)

                # 替换 ';' 为 ',' 后生成 hex_data 列表
                hex_data_raw = [p.strip() for p in params]
                hex_data_replaced = [data.replace(';', ',') for data in hex_data_raw]

                # 扁平化 hex_data_replaced 列表并移除空值
                flat_hex_data = [item for sublist in [data.split(',') for data in hex_data_replaced] for item in sublist
                                 if item.strip()]
                # print(f"处理的扁平数据: {flat_hex_data}")

                # 跳过指定的数据
                if skip_data > 0 and len(flat_hex_data) >= skip_data:
                    print(f"跳过第 {skip_data} 个数据，原数据: {flat_hex_data}")
                    flat_hex_data.pop(skip_data - 1)  # 跳过第 skip_data 个数据（索引从0开始）
                    # print(f"跳过后的数据: {flat_hex_data}")

                # 筛选出以 0x 开头的数据
                if include_non_hex:
                    # hex_data = flat_hex_data
                    # hex_data = [f"0x{int(item, 16):X}" for item in flat_hex_data]
                    # 处理 flat_hex_data，确保每个数据项都以 '0x' 开头，并且长度至少为两位
                    hex_data = [
                        f"0x{int(item, 16):02X}" if not item.startswith("0x") else item
                        for item in flat_hex_data
                    ]
                    # print("include_non_hex")
                else:
                    hex_data = [data for data in flat_hex_data if data.startswith("0x")]

                if header_value is None:
                    header_value = 0x29  # 默认指令头为0x29

                array_name = f"cmd{index}"
                data_length = len(hex_data)
                array_content = [f"0x{header_value:02X}", f"0x{data_length:02X}"] + ["0x00"] + hex_data
                array_definition = f"static uint8_t {array_name}[] = {{{', '.join(array_content)}}};"
                extracted_data.append(array_definition)
                index += 1
                extracted_array_name.append(f"{array_name},")
    output_text = "\nstatic uint8_t* commands[] = {\n"
    for i, text in enumerate(extracted_array_name):
        if i % 8 == 0:
            output_text += "\n"
        output_text += text
    output_text += "\n};\n"

    return extracted_data, output_text

# ==================== 提取数据处理核心 ====================
def extract_gui():
    def extract_data():
        input_text = input_textbox.get("1.0", tk.END)
        command_name = command_entry.get().strip()
        header_value_str = header_entry.get().strip()
        index_start_str = index_entry.get().strip()
        start_find_value = start_find_entry.get()
        end_find_value = end_find_entry.get()
        include_non_hex = include_non_hex_var.get()
        use_alternative_rule = alternative_rule_var.get()

        # 获取数据分隔符
        if use_custom_separator_var.get():
            separator = separator_entry.get() or ',;'  # 默认为逗号
        else:
            separator = ','  # 默认分隔符为逗号

        # 读取并处理 skip_data
        try:
            skip_data = int(skip_data_entry.get().strip()) if skip_data_var.get() else 0
        except ValueError:
            skip_data = 0

        if not command_name:
            command_name = "GEN_WR"
        if not start_find_value:
            start_find_value = "("
        if not end_find_value:
            end_find_value = ")"

        if header_value_str.startswith("0x"):
            header_value = int(header_value_str, 16)
        else:
            header_value = None

        if index_start_str.isdigit():
            index_start = int(index_start_str)
        else:
            index_start = 0

        extracted_data, output_text = extract_specific_command_data(
            input_text, command_name, header_value, index_start, start_find_value, end_find_value, include_non_hex,
            use_alternative_rule, skip_data, separator
        )

        output_textbox.delete("1.0", tk.END)
        for data in extracted_data:
            output_textbox.insert(tk.END, data + "\n")
        output_textbox.insert(tk.END, output_text + "\n")

    extract_window = tk.Toplevel()
    extract_window.title("提取指定命令数据")

    paned_window = tk.PanedWindow(extract_window, orient=tk.HORIZONTAL, sashrelief=tk.RAISED, sashwidth=5)
    paned_window.pack(fill=tk.BOTH, expand=True)

    left_frame = tk.Frame(extract_window)
    right_frame = tk.Frame(extract_window)

    paned_window.add(left_frame)
    paned_window.add(right_frame)

    input_label = tk.Label(left_frame, text="请粘贴要处理的命令文本:")
    input_label.pack(fill=tk.X, padx=5, pady=5)

    input_textbox = scrolledtext.ScrolledText(left_frame, width=40, height=15)
    input_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

    command_label = tk.Label(left_frame, text="请输入要提取的命令名称（例如：GEN_WR）： 留空则默认为GEN_WR")
    command_label.pack(fill=tk.X, padx=5, pady=5)

    command_entry = tk.Entry(left_frame)
    command_entry.pack(fill=tk.X, padx=5, pady=5)

    header_label = tk.Label(left_frame, text="请输入指令头的十六进制数值（例如：0x29），留空则默认为0x29:")
    header_label.pack(fill=tk.X, padx=5, pady=5)

    header_entry = tk.Entry(left_frame)
    header_entry.pack(fill=tk.X, padx=5, pady=5)

    index_label = tk.Label(left_frame, text="请输入起始索引值（例如：0），默认为0:")
    index_label.pack(fill=tk.X, padx=5, pady=5)

    index_entry = tk.Entry(left_frame)
    index_entry.pack(fill=tk.X, padx=5, pady=5)

    start_find_label = tk.Label(left_frame, text="请输入有效数据最左边的符号 查找的值（例如：'GEN_WR(0xFF,0x80,0x57) 则输入(或则R(，）默认为'(':")
    start_find_label.pack(fill=tk.X, padx=5, pady=5)

    start_find_entry = tk.Entry(left_frame)
    start_find_entry.pack(fill=tk.X, padx=5, pady=5)

    end_find_label = tk.Label(left_frame, text="请输入有效数据最右边的符号 查找的值（例如：'GEN_WR(0xFF,0x80,0x57) 则输入)或则;，）默认为')':")
    end_find_label.pack(fill=tk.X, padx=5, pady=5)

    end_find_entry = tk.Entry(left_frame)
    end_find_entry.pack(fill=tk.X, padx=5, pady=5)

    # 创建一个框架用于放置 Checkbutton 控件、跳过数据的 Entry 控件和分隔符文本框
    options_frame = tk.Frame(left_frame)
    options_frame.pack(fill=tk.X, padx=5, pady=5)

    include_non_hex_var = tk.BooleanVar()
    include_non_hex_check = tk.Checkbutton(options_frame, text="包含不以 '0x' 开头的数据", variable=include_non_hex_var)
    include_non_hex_check.pack(side=tk.LEFT, padx=5)

    alternative_rule_var = tk.BooleanVar()
    alternative_rule_check = tk.Checkbutton(options_frame, text="使用其他规则", variable=alternative_rule_var)
    alternative_rule_check.pack(side=tk.LEFT, padx=5)

    skip_data_var = tk.BooleanVar()
    skip_data_check = tk.Checkbutton(options_frame, text="跳过第N个数据", variable=skip_data_var)
    skip_data_check.pack(side=tk.LEFT, padx=5)

    skip_data_entry = tk.Entry(options_frame, width=5, state=tk.DISABLED)
    skip_data_entry.pack(side=tk.LEFT, padx=5)

    use_custom_separator_var = tk.BooleanVar()
    use_custom_separator_check = tk.Checkbutton(options_frame, variable=use_custom_separator_var)
    use_custom_separator_check.pack(side=tk.LEFT, padx=5)

    separator_label = tk.Label(options_frame, text="自定义有效数据分隔符（例如：',', ';'）：")
    separator_label.pack(side=tk.LEFT, padx=5)

    separator_entry = tk.Entry(options_frame, width=5)
    separator_entry.pack(side=tk.LEFT, padx=5)

    # 当勾选“跳过第N个数据”时，启用 skip_data_entry 控件并设置默认值为2
    def toggle_skip_data():
        if skip_data_var.get():
            skip_data_entry.config(state=tk.NORMAL)
            if skip_data_entry.get().strip() == '':
                skip_data_entry.insert(0, '2')
        else:
            skip_data_entry.config(state=tk.DISABLED)
            skip_data_entry.delete(0, tk.END)  # 清除内容以避免不必要的显示

    skip_data_check.config(command=toggle_skip_data)

    # 当勾选“使用自定义分隔符”时，启用 separator_entry 控件，否则禁用它
    def toggle_separator_entry():
        if use_custom_separator_var.get():
            separator_entry.config(state=tk.NORMAL)
        else:
            separator_entry.config(state=tk.DISABLED)
            separator_entry.delete(0, tk.END)  # 清除内容以避免不必要的显示

    use_custom_separator_check.config(command=toggle_separator_entry)

    extract_button = tk.Button(left_frame, text="提取数据", command=extract_data)
    extract_button.pack(pady=10)

    output_label = tk.Label(right_frame, text="提取结果:")
    output_label.pack(fill=tk.X, padx=5, pady=5)

    output_textbox = scrolledtext.ScrolledText(right_frame, width=40, height=15)
    output_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

    extract_window.mainloop()


# ==================== 转换数据处理核心 ====================
def convert_gui():
    def convert_data():
        hex_data = hex_textbox.get("1.0", tk.END)
        converted_data = convert_hex_to_array(hex_data)

        converted_textbox.delete("1.0", tk.END)
        converted_textbox.insert(tk.END, "{" + "\n")
        for data in converted_data:
            # converted_textbox.insert(tk.END, "  " + "\n")
            converted_textbox.insert(tk.END, data + "\n")
        converted_textbox.insert(tk.END, "};" + "\n")

    convert_window = tk.Toplevel()
    convert_window.title("PPS 十六进制数据转换为数组")

    paned_window = PanedWindow(convert_window, orient=tk.HORIZONTAL, sashrelief=tk.RAISED, sashwidth=5)
    paned_window.pack(fill=tk.BOTH, expand=True)

    left_frame = tk.Frame(convert_window)
    right_frame = tk.Frame(convert_window)

    paned_window.add(left_frame)
    paned_window.add(right_frame)

    hex_label = tk.Label(left_frame, text="请粘贴要转换的PPS 十六进制数据（每行以空格分隔）:")
    hex_label.pack(fill=tk.X, padx=5, pady=5)

    hex_textbox = scrolledtext.ScrolledText(left_frame, width=40, height=15)
    hex_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

    convert_button = tk.Button(left_frame, text="转换数据", command=convert_data)
    convert_button.pack(pady=10)

    converted_label = tk.Label(right_frame, text="转换后的数据:")
    converted_label.pack(fill=tk.X, padx=5, pady=5)

    converted_textbox = scrolledtext.ScrolledText(right_frame, width=40, height=15)
    converted_textbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

# ==================== SPI数据处理核心 ====================
def extract_spi():
    # 创建一个隐藏的Tk窗口
    tk.Tk().withdraw()
    # 打开文件选择对话框
    file_path = askopenfilename(title="选择CSV文件", filetypes=[("CSV files", "*.csv")])
    if not file_path:
        # messagebox.showwarning("警告", "未选择文件！")
        debug_print("用户取消选择SPI.csv文件")
        return

        # 读取CSV文件
    data = pd.read_csv(file_path)
    # 初始化结果
    current_group_sdi = []
    current_group_sdo = []
    groups = []
    handshake_count = 0
    # 遍历每一行数据
    for index, row in data.iterrows():
        status = row.iloc[0].strip('="')  # 使用iloc来获取第二列（Status(8 bits data)）
        cleaned_row = [item.strip('=" ') for item in row.iloc[1:17]]  # 清洗D0到D15的内容
        cleaned_row = [f"0x{item}" for item in cleaned_row if item]  # 去除空项例如""
        # print(status)
        if status == 'Idle':
            # handshake_count += 1
            # groups.append(f"handshake{handshake_count}")
            # if current_group_sdi:
            #     groups.append(current_group_sdi)
            #     current_group_sdi = []

            if current_group_sdo:
                groups.append(current_group_sdo)
                # groups.append(f"const uint8 t tp _reg_{handshake_count}[]={current_group_sdo}")
                current_group_sdo = []
        else:
            # 将SDI和SDO的数据提取到当前组
            # if status == 'SDI':
            #     for d_data in cleaned_row:
            #         current_group_sdi.append(d_data)  # 提取D0到D15的内容

            if status == 'SDO':
                for d_data in cleaned_row:
                    current_group_sdo.append(d_data)  # 提取D0到D15的内容

    # 添加最后一个组（如果存在）
    # if current_group_sdi:
    #     groups.append(current_group_sdi)
    if current_group_sdo:
        groups.append(current_group_sdo)

        # 输出结果到output_textbox
    output_textbox.delete(1.0, tk.END)  # 清空之前的内容
    for group in groups:
        # print(group)
        output_textbox.delete("1.0", tk.END)
    for index , group in enumerate(groups):
        group_string = str(group)
        if 'handshake' not in group:
            group_string = ','.join(group)
            group_string = "const uint8_t tp _reg_" + str(index) +  "[]= {" + group_string + "};"
            # groups.append(f"const uint8 t tp _reg_{handshake_count}[]={current_group_sdo}")
        output_textbox.insert(tk.END, group_string + "\n")
    # output_textbox.insert(tk.END, output_text + "\n")

# ==================== IIC数据处理核心 ====================
def extract_iic_data():
    def detect_file_encoding(file_path):
        """自动检测文件编码"""
        debug_print("开始检测文件编码...")
        try:
            with open(file_path, 'rb') as f:
                rawdata = f.read(20000)
                result = chardet.detect(rawdata)
                debug_print(f"检测结果：{result}")
                return result['encoding'] or 'utf-8'
        except Exception as e:
            debug_print(f"编码检测失败：{str(e)}")
            return 'utf-8'

    def safe_read_csv(file_path):
        """安全读取CSV文件"""
        encodings = [
            detect_file_encoding(file_path),
            'utf-8-sig',
            'gb18030',
            'latin-1',
            'utf-8'
        ]

        for idx, encoding in enumerate(encodings):
            debug_print(f"尝试编码 #{idx + 1}: {encoding}")
            try:
                # 数据清洗优化
                df = pd.read_csv(file_path, encoding=encoding, engine='python', on_bad_lines='warn')

                # 批量处理字符串列
                str_cols = df.select_dtypes(include='object').columns
                if not str_cols.empty:
                    df[str_cols] = df[str_cols].apply(
                        lambda col: col.str.strip('"= \t').replace(r'^\s*$', pd.NA, regex=True)
                    )

                return df
            except UnicodeDecodeError:
                continue
            except Exception as e:
                debug_print(f"编码 {encoding} 读取失败：{str(e)}")
                raise
        raise ValueError("所有编码尝试失败")

    def find_previous_wr(df, start_index):
        """向前查找最近的WR记录"""
        # debug_print(f"从行 {start_index + 1} 向前查找WR...")
        for j in range(start_index - 1, max(-1, start_index - 50), -1):  # 最多向前查50行
            current_addr = df.iloc[j]['Address(7b)']
            # debug_print(f"检查行 {j + 1} 地址: {current_addr}")
            if 'WR' in current_addr:
                # debug_print(f"在行 {j + 1} 找到有效WR记录")
                return j
        # debug_print("未找到关联的WR记录")
        return None

    def process_iic_records(df, mode='standard'):
        """处理IIC记录（新增直接提取模式）"""
        # debug_print(f"启动数据处理流程 - 模式：{'直接提取' if mode == 'direct' else '标准'}...")
        debug_print("标准提取模式\n")
        results = {}
        content_registry = {}
        name_counters = defaultdict(int)

        try:
            # 预处理地址列
            df['Address(7b)'] = df['Address(7b)'].fillna('').apply(
                lambda x: re.sub(r'[^A-Z]', '', str(x).upper())
            )

            i = 0
            while i < len(df):
                current_row = df.iloc[i]
                addr = current_row['Address(7b)']
                # debug_print(f"\n=== 发现addr（行 {addr}） ===")
                if 'RD' in addr:
                    # debug_print(f"\n=== 发现读操作（行 {i + 1}） ===")
                    wr_index = find_previous_wr(df, i)

                    # 生成基名
                    if wr_index is not None:
                        wr_d0 = clean_hex_value(df.iloc[wr_index]['D0'])
                        base_name = f"Reg_{wr_d0.replace('0x', '').upper()}" if wr_d0 else None
                    else:
                        rd_d0 = clean_hex_value(current_row.get('D0', ''))
                        rd_d1 = clean_hex_value(current_row.get('D1', ''))
                        base_name = f"Reg_{rd_d0}_{rd_d1}" if rd_d0 and rd_d1 else None

                    if not base_name:
                        # debug_print("❌ 基名生成失败，跳过")
                        i += 1
                        continue

                    # 数据收集逻辑
                    data_block = []
                    current_index = i
                    data_valid = True

                    while data_valid and current_index < len(df):
                        # 遇到新操作立即终止
                        if current_index != i and ('WR' in df.iloc[current_index]['Address(7b)']
                                                   or 'RD' in df.iloc[current_index]['Address(7b)']):
                            # debug_print(f"发现新操作，终止于行 {current_index + 1}")
                            break

                        # 处理当前行数据
                        row_data = []
                        for k in range(8):
                            val = clean_hex_value(df.iloc[current_index].get(f'D{k}', ''))
                            if val:
                                row_data.append(val.upper())
                            else:
                                # 遇到空D位立即终止
                                if row_data:
                                    data_block.extend(row_data)
                                    # debug_print(f"行{current_index + 1}的D{k}为空，保留已收集数据")
                                # else:
                                #     debug_print(f"行{current_index + 1}无有效数据")
                                data_valid = False
                                break  # 跳出D位循环

                        if data_valid:
                            if row_data:
                                data_block.extend(row_data)
                                # debug_print(f"行{current_index + 1}收集数据：{row_data}")
                            current_index += 1
                        else:
                            current_index += 1  # 移动到下一行但终止循环
                            break

                    # 去重处理
                    content_hash = hashlib.md5(str(data_block).encode()).hexdigest()
                    if content_hash in content_registry:
                        pass #donoting
                        # debug_print(f"内容重复：{content_registry[content_hash]}")
                    else:
                        # 生成最终名称
                        name_counters[base_name] += 1
                        final_name = f"{base_name}_{name_counters[base_name]}" if name_counters[
                                                                                      base_name] > 1 else base_name
                        content_registry[content_hash] = final_name
                        results[final_name] = data_block
                        # debug_print(f"生成新寄存器：{final_name}（{len(data_block)}字节）")

                    i = current_index
                else:
                    i += 1

            debug_print(f"\n✅ 处理完成，共生成 {len(results)} 个寄存器")
            return results

        except Exception as e:
            log_exception(e)
            return {}

    def _process_direct_mode(self, df):
        """直接提取模式处理逻辑"""
        results = {}
        content_registry = {}
        name_counters = defaultdict(int)
        i = 0

        while i < len(df):
            current_row = df.iloc[i]
            addr = current_row['Address(7b)']
            debug_print("直接提取模式\n")
            if 'RD' in addr:
                debug_print(f"\n[直接模式] 发现RD记录（行 {i + 1}）")

                # 生成基名
                rd_d0 = clean_hex_value(current_row.get('D0', ''))
                rd_d1 = clean_hex_value(current_row.get('D1', ''))
                base_name = f"Rd_{rd_d0.replace('0x', '')}_{rd_d1.replace('0x', '')}" if rd_d0 and rd_d1 else f"Rd_{i + 1}"

                # 数据收集
                data_block = []
                current_index = i
                data_valid = True

                while data_valid and current_index < len(df):
                    if current_index != i and 'RD' in df.iloc[current_index]['Address(7b)']:
                        debug_print(f"行{current_index + 1}发现新RD，终止收集")
                        break

                    row_data = []
                    for k in range(8):
                        val = df.iloc[current_index].get(f'D{k}', '')
                        hex_val = clean_hex_value(val)

                        if hex_val:
                            row_data.append(hex_val)
                        else:
                            if str(val).strip():
                                debug_print(f"行{current_index + 1}的D{k}存在无效值: '{val}'")
                            data_valid = False
                            break

                    if data_valid:
                        data_block.extend(row_data)
                        current_index += 1
                    else:
                        debug_print(f"行{current_index + 1}数据无效，终止收集")
                        break

                # 结果处理
                if data_block:
                    content_hash = hashlib.md5(str(data_block).encode()).hexdigest()
                    if content_hash in content_registry:
                        debug_print(f"内容重复：{content_registry[content_hash]}")
                    else:
                        name_counters[base_name] += 1
                        final_name = f"{base_name}_{name_counters[base_name]}" if name_counters[
                                                                                      base_name] > 1 else base_name
                        content_registry[content_hash] = final_name
                        results[final_name] = data_block
                        debug_print(f"生成新数据块：{final_name}（{len(data_block)}字节）")

                i = current_index
            else:
                i += 1

        return results

    def generate_c_code(results):
        """生成符合规范的C代码"""
        code_lines = ["对于内存分配,要看单片机是几位的 若是8位的 考虑内存对齐问题数组占用内存也是一样大小的\n"]
        for reg_name, data in results.items():
            # 数组声明
            code = f"uint8_t {reg_name}[] = {{\n"

            # 处理每个数据项
            entries = []
            for idx, item in enumerate(data):
                # 统一格式：0x + 大写十六进制
                hex_val = f"0x{item.replace('0x', '').upper().zfill(2)}"
                # 最后一个元素不加逗号
                if idx == len(data) - 1:
                    entries.append(f"    {hex_val}")
                else:
                    entries.append(f"    {hex_val},")

            # 组合代码块
            code += "\n".join(entries)
            code += "\n};\n"
            code_lines.append(code)
        return "\n".join(code_lines)

    # ==================== GUI流程 ====================
    try:
        file_path = filedialog.askopenfilename(filetypes=[("CSV Files", "*.csv")])
        if not file_path:
            debug_print("用户取消选择IIC.csv")
            return

        debug_print(f"开始处理文件：{os.path.basename(file_path)}")
        df = safe_read_csv(file_path)
        debug_print(f"文件读取成功，共 {len(df)} 行")

        if iic_mode_var == 'direct':
            results = _process_direct_mode(df)
        else:
            results = process_iic_records(df)
        debug_print(f"处理完成，生成 {len(results)} 个寄存器数组")

        if not results:
            show_error("无数据", "未找到有效的WR-RD数据对")
            return

        # 显示结果窗口
        result_window = tk.Toplevel()
        result_window.title("IIC数据提取结果")

        text_area = scrolledtext.ScrolledText(result_window, wrap=tk.WORD, width=80, height=30)
        text_area.pack(expand=True, fill='both')

        # code =
        debug_print(generate_c_code(results))
        text_area.insert(tk.END, generate_c_code(results))

    except Exception as e:
        log_exception(e)


def create_main_gui():
    global output_textbox
    global iic_mode_var

    root = tk.Tk()
    root.title("硬件数据分析工具 v6.1")
    root.geometry("1400x900")

    # 使用主题样式
    style = ttk.Style()
    style.theme_use('clam')

    # 初始化模式变量
    iic_mode_var = tk.StringVar(value='direct')

    # ==================== 控制面板 ====================
    control_frame = ttk.Frame(root, padding=(20, 10))
    control_frame.pack(fill=tk.X)

    # 模式选择组件
    mode_frame = ttk.Frame(control_frame)
    ttk.Label(mode_frame, text="IIC模式:").pack(side=tk.LEFT)
    ttk.Radiobutton(mode_frame, text="直接模式", variable=iic_mode_var,
                    value='direct').pack(side=tk.LEFT, padx=10)
    ttk.Radiobutton(mode_frame, text="标准模式", variable=iic_mode_var,
                    value='standard').pack(side=tk.LEFT)
    mode_frame.pack(side=tk.LEFT, padx=20)

    # 功能按钮
    buttons = [
        ("IIC协议解析", extract_iic_data, "#4CAF50"),
        ("SPI协议解析", extract_spi, "#2196F3"),
        ("16进制增加0x", convert_gui, "#9C27B0"),
        ("BTA—CSV批处理", open_csv_file_and_process, "#FF9800"),
        ("指令提取", extract_gui, "#009688")
    ]

    # 使用pack布局替代grid
    button_container = ttk.Frame(control_frame)
    button_container.pack(side=tk.RIGHT, padx=20)

    for text, cmd, color in buttons:
        btn = tk.Button(button_container, text=text, command=cmd,
                        width=15, height=2, bg=color, fg="white",
                        font=("微软雅黑", 10, "bold"),
                        relief=tk.GROOVE)
        btn.pack(side=tk.LEFT, padx=5)

    # ==================== 输出面板 ====================
    output_frame = ttk.Frame(root)
    output_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

    output_textbox = scrolledtext.ScrolledText(
        output_frame,
        wrap=tk.WORD,
        font=("Consolas", 10),
        undo=True,
        padx=10,
        pady=10,
        bg="#2B2B2B",
        fg="#A9B7C6"
    )
    output_textbox.pack(fill=tk.BOTH, expand=True)

    # ==================== 状态栏 ====================
    status_bar = ttk.Label(root, text="就绪 ▶▶  系统初始化完成",
                           relief=tk.SUNKEN, anchor=tk.W,
                           font=("微软雅黑", 9), background="#E3F2FD")
    status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    # ==================== 右键菜单 ====================
    context_menu = tk.Menu(root, tearoff=0)
    context_menu.add_command(label="清空输出", command=lambda: output_textbox.delete(1.0, tk.END))
    context_menu.add_command(label="导出日志", command=export_log)

    def show_context_menu(event):
        try:
            context_menu.tk_popup(event.x_root, event.y_root)
        finally:
            context_menu.grab_release()

    output_textbox.bind("<Button-3>", show_context_menu)

    root.mainloop()


# 示例导出日志函数
def export_log():
    file_path = filedialog.asksaveasfilename(
        defaultextension=".log",
        filetypes=[("Log Files", "*.log"), ("All Files", "*.*")]
    )
    if file_path:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(output_textbox.get(1.0, tk.END))


def read_verification_code(filename):
    if os.path.exists(filename):
        with open(filename, 'r') as f:
            verification_code = f.read().strip()
            if verification_code:
                return verification_code
            else:
                return None
    else:
        return None


def save_verification_code(filename, verification_code):
    print("正在写入" + verification_code)
    with open(filename, 'w') as f:
        f.write(verification_code)
        messagebox.showinfo("保存成功", "校验码已保存, 请重新启动APP")


verification_result = False  # 全局变量来存储验证结果

def input_verification_code(file_path):
    def save_code():
        global verification_result
        code = entry.get().strip()
        print("用户输入的校验码: " + code)
        if code:
            try:
                verify_state = verify_code(code)
                print(f"验证状态: {verify_state}")
                if verify_state:
                    save_verification_code(file_path, code)
                    verification_result = True  # 成功时设置为 True
                    window.destroy()  # 关闭窗口
                else:
                    messagebox.showerror("校验失败", "校验码错误，请重新输入。")
                    verification_result = False  # 失败时设置为 False
            except Exception as e:
                print(f"保存校验码过程中出现错误: {e}")
                verification_result = False  # 异常时设置为 False
        else:
            messagebox.showerror("错误", "请输入校验码。")
            verification_result = False  # 输入为空时设置为 False

    def verify_code(code):
        try:
            if code:
                verification_state = validate_license_code(code)
            else:
                local_verification_code = read_verification_code(file_path)
                verification_state = validate_license_code(local_verification_code)
                print("重新读取的校验码: " + local_verification_code)
            return verification_state
        except Exception as e:
            print(f"验证过程中出现错误: {e}")
            return False

    window = tk.Tk()
    window.title("输入校验码")

    label = tk.Label(window, text="请输入校验码：")
    label.pack(pady=10)

    entry = tk.Entry(window, show='*')
    entry.pack(pady=10)

    button = tk.Button(window, text="保存", command=save_code)
    button.pack(pady=10)

    window.mainloop()

    return verification_result  # 返回全局变量的值


from tkinter import scrolledtext, simpledialog

# 添加从 crypto_utils.py 移植的函数

def show_license_code(license_code):
    root = tk.Tk()
    root.title("License Code")

    # 创建一个 Text 小部件以显示 license_code
    text_widget = scrolledtext.ScrolledText(root, width=40, height=10, wrap=tk.WORD)
    text_widget.pack(fill=tk.BOTH, expand=True)

    # 插入 license_code 到 Text 小部件
    text_widget.insert(tk.END, f"License Code:\n{license_code}")

    # 允许用户选择和复制文本
    text_widget.configure(state='normal')  # 使 Text 小部件可编辑
    text_widget.focus_set()  # 设置焦点到 Text 小部件

    # 添加一个 OK 按钮以关闭窗口
    ok_button = tk.Button(root, text="OK", command=root.destroy, padx=10, pady=5)
    ok_button.pack(pady=5)

    root.mainloop()


def get_mac_address_from_user():
    root = tk.Tk()
    root.withdraw()  # Hide the root window
    mac_address = simpledialog.askstring("MAC Address", "请输入MAC地址:")
    return mac_address
